#ifndef DISPENSEHEADCONFIG_H
#define DISPENSEHEADCONFIG_H

#include "XtMotion/xtdispenser.h"
#include "configManager/configobject.h"
#include "enumhelper.h"

class LaserToCameraOffsetCaliParam : public ConfigObject
{
    Q_OBJECT

    Q_PROPERTY(double moveRange READ moveRange WRITE setMoveRange NOTIFY moveRangeChanged)
    Q_PROPERTY(
        double velocityRatioLimit READ velocityRatioLimit WRITE setVelocityRatioLimit NOTIFY velocityRatioLimitChanged)
    Q_PROPERTY(int windowLen READ windowLen WRITE setWindowLen NOTIFY windowLenChanged)
    Q_PROPERTY(int deltaRatio READ deltaRatio WRITE setDeltaRatio NOTIFY deltaRatioChanged)
    Q_PROPERTY(bool cmpHeightDelta READ cmpHeightDelta WRITE setCmpHeightDelta NOTIFY cmpHeightDeltaChanged)
    Q_PROPERTY(double heightDelta READ heightDelta WRITE setHeightDelta NOTIFY heightDeltaChanged)

public:
    LaserToCameraOffsetCaliParam(QObject *parent = nullptr) : ConfigObject(parent)
    {
        init();
    }

    double moveRange() const
    {
        return m_moveRange;
    }

    double velocityRatioLimit() const
    {
        return m_velocityRatioLimit;
    }

    int windowLen() const
    {
        return m_windowLen;
    }

    int deltaRatio() const
    {
        return m_deltaRatio;
    }

    bool cmpHeightDelta() const
    {
        return m_cmpHeightDelta;
    }

    double heightDelta() const
    {
        return m_heightDelta;
    }

public slots:
    void setMoveRange(double moveRange)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_moveRange, moveRange))
            return;

        m_moveRange = moveRange;
        emit moveRangeChanged(m_moveRange);
    }

    void setVelocityRatioLimit(double velocityRatioLimit)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_velocityRatioLimit, velocityRatioLimit))
            return;

        m_velocityRatioLimit = velocityRatioLimit;
        emit velocityRatioLimitChanged(m_velocityRatioLimit);
    }

    void setWindowLen(int windowLen)
    {
        if (m_windowLen == windowLen)
            return;

        if (windowLen < 2)
        {
            qCritical() << tr("windowLen must greater than 1!");
            emit windowLenChanged(m_windowLen);
            return;
        }
        m_windowLen = windowLen;
        emit windowLenChanged(m_windowLen);
    }

    void setDeltaRatio(int deltaRatio)
    {
        if (m_deltaRatio == deltaRatio)
            return;

        m_deltaRatio = deltaRatio;
        emit deltaRatioChanged(m_deltaRatio);
    }

    void setCmpHeightDelta(bool cmpHeightDelta)
    {
        if (m_cmpHeightDelta == cmpHeightDelta)
            return;

        m_cmpHeightDelta = cmpHeightDelta;
        emit cmpHeightDeltaChanged(m_cmpHeightDelta);
    }

    void setHeightDelta(double heightDelta)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_heightDelta, heightDelta))
            return;

        m_heightDelta = heightDelta;
        emit heightDeltaChanged(m_heightDelta);
    }

signals:
    void moveRangeChanged(double moveRange);

    void velocityRatioLimitChanged(double velocityRatioLimit);

    void windowLenChanged(int windowLen);

    void deltaRatioChanged(int deltaRatio);

    void cmpHeightDeltaChanged(bool cmpHeightDelta);

    void heightDeltaChanged(double heightDelta);

private:
    double m_moveRange = 10;
    double m_velocityRatioLimit = 0.01;
    int m_windowLen = 10;
    int m_deltaRatio = 30;
    bool m_cmpHeightDelta = true;
    double m_heightDelta = 1;
};

class GlueCheckParam : public ConfigObject
{
    Q_OBJECT

    Q_PROPERTY(double resoultion READ resoultion WRITE setResoultion NOTIFY resoultionChanged)
    Q_PROPERTY(double maxGlueWidth READ maxGlueWidth WRITE setMaxGlueWidth NOTIFY maxGlueWidthChanged)
    Q_PROPERTY(double minGlueWidth READ minGlueWidth WRITE setMinGlueWidth NOTIFY minGlueWidthChanged)
    Q_PROPERTY(double aveGlueWidthUpperLimit READ aveGlueWidthUpperLimit WRITE setAveGlueWidthUpperLimit NOTIFY
                   aveGlueWidthUpperLimitChanged)
    Q_PROPERTY(double aveGlueWidthLowerLimit READ aveGlueWidthLowerLimit WRITE setAveGlueWidthLowerLimit NOTIFY
                   aveGlueWidthLowerLimitChanged)

public:
    GlueCheckParam(QObject *parent = nullptr) : ConfigObject(parent)
    {
        init();
    }

    double resoultion() const
    {
        return m_resoultion;
    }

    double maxGlueWidth() const
    {
        return m_maxGlueWidth;
    }

    double minGlueWidth() const
    {
        return m_minGlueWidth;
    }

    double aveGlueWidthUpperLimit() const
    {
        return m_aveGlueWidthUpperLimit;
    }

    double aveGlueWidthLowerLimit() const
    {
        return m_aveGlueWidthLowerLimit;
    }

public slots:
    void setResoultion(double resoultion)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_resoultion, resoultion))
            return;

        m_resoultion = resoultion;
        emit resoultionChanged(m_resoultion);
    }

    void setMaxGlueWidth(double maxGlueWidth)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_maxGlueWidth, maxGlueWidth))
            return;

        m_maxGlueWidth = maxGlueWidth;
        emit maxGlueWidthChanged(m_maxGlueWidth);
    }

    void setMinGlueWidth(double minGlueWidth)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_minGlueWidth, minGlueWidth))
            return;

        m_minGlueWidth = minGlueWidth;
        emit minGlueWidthChanged(m_minGlueWidth);
    }

    void setAveGlueWidthUpperLimit(double aveGlueWidthUpperLimit)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_aveGlueWidthUpperLimit, aveGlueWidthUpperLimit))
            return;

        m_aveGlueWidthUpperLimit = aveGlueWidthUpperLimit;
        emit aveGlueWidthUpperLimitChanged(m_aveGlueWidthUpperLimit);
    }

    void setAveGlueWidthLowerLimit(double aveGlueWidthLowerLimit)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_aveGlueWidthLowerLimit, aveGlueWidthLowerLimit))
            return;

        m_aveGlueWidthLowerLimit = aveGlueWidthLowerLimit;
        emit aveGlueWidthLowerLimitChanged(m_aveGlueWidthLowerLimit);
    }

signals:
    void resoultionChanged(double resoultion);

    void maxGlueWidthChanged(double maxGlueWidth);

    void minGlueWidthChanged(double minGlueWidth);

    void aveGlueWidthUpperLimitChanged(double aveGlueWidthUpperLimit);

    void aveGlueWidthLowerLimitChanged(double aveGlueWidthLowerLimit);

private:
    double m_resoultion = 0;
    double m_maxGlueWidth = 0;
    double m_minGlueWidth = 0;
    double m_aveGlueWidthUpperLimit = 0;
    double m_aveGlueWidthLowerLimit = 0;
};

class DispenseHeadCommonConfig : public ConfigObject
{
    Q_OBJECT

    Q_PROPERTY(bool disableLeftDispHead READ disableLeftDispHead WRITE setDisableLeftDispHead NOTIFY
                   disableLeftDispHeadChanged)
    Q_PROPERTY(bool disableRightDispHead READ disableRightDispHead WRITE setDisableRightDispHead NOTIFY
                   disableRightDispHeadChanged)
    Q_PROPERTY(bool executeGlueCheck READ executeGlueCheck WRITE setExecuteGlueCheck NOTIFY executeGlueCheckChanged)
    Q_PROPERTY(double rightDH2LeftDHSafetyRange READ rightDH2LeftDHSafetyRange WRITE setRightDH2LeftDHSafetyRange NOTIFY
                   rightDH2LeftDHSafetyRangeChanged)

    Q_PROPERTY(double measureHeightVelocityRatio READ measureHeightVelocityRatio WRITE setMeasureHeightVelocityRatio
                   NOTIFY measureHeightVelocityRatioChanged)

    Q_PROPERTY(LaserToCameraOffsetCaliParam *laserToCameraOffsetCaliParam READ laserToCameraOffsetCaliParam)

    Q_PROPERTY(int shotGlueDotTime READ shotGlueDotTime WRITE setShotGlueDotTime NOTIFY shotGlueDotTimeChanged)
    Q_PROPERTY(double shotGlueZOffset READ shotGlueZOffset WRITE setShotGlueZOffset NOTIFY shotGlueZOffsetChanged)
    Q_PROPERTY(double initAngle READ initAngle WRITE setInitAngle NOTIFY initAngleChanged)
    Q_PROPERTY(double readyForDispenseZOffset READ readyForDispenseZOffset WRITE setReadyForDispenseZOffset NOTIFY
                   readyForDispenseZOffsetChanged)

    Q_PROPERTY(QString measureHeightFre READ measureHeightFre WRITE setMeasureHeightFre NOTIFY measureHeightFreChanged)
    Q_PROPERTY(double measureHeightXShift READ measureHeightXShift WRITE setMeasureHeightXShift NOTIFY
                   measureHeightXShiftChanged)
    Q_PROPERTY(double measureHeightPosYShift READ measureHeightPosYShift WRITE setMeasureHeightPosYShift NOTIFY
                   measureHeightPosYShiftChanged)

    Q_PROPERTY(QString dispensePathFileName READ dispensePathFileName WRITE setDispensePathFileName NOTIFY
                   dispensePathFileNameChanged)

    Q_PROPERTY(DispenserConfig *dispenserConfig READ dispenserConfig)
    Q_PROPERTY(XtFlyDispensingConfig *xtFlyDispensingConfig READ xtFlyDispensingConfig)
    Q_PROPERTY(GlueCheckParam *glueCheckParam READ glueCheckParam)

public:
    enum MeasureHeightFre
    {
        EveryMaterial,
        EveryTray,
        OnlyOnce
    };
    Q_ENUM(MeasureHeightFre)

    static EnumHelper<MeasureHeightFre> &MeasureHeightFreEnumInfo()
    {
        static EnumHelper<MeasureHeightFre> instance(staticMetaObject, "MeasureHeightFre");
        return instance;
    }

    DispenseHeadCommonConfig(QObject *parent = nullptr) : ConfigObject(parent)
    {
        m_dispenserConfig = new DispenserConfig(this);
        m_xtFlyDispensingConfig = new XtFlyDispensingConfig(this);
        m_laserToCameraOffsetCaliParam = new LaserToCameraOffsetCaliParam(this);
        m_glueCheckParam = new GlueCheckParam(this);
        setOptionalProperty("measureHeightFre", toVariantList(MeasureHeightFreEnumInfo().names()));
        hide("dispenserConfig");
        init();
    }

    double measureHeightVelocityRatio() const
    {
        return m_measureHeightVelocityRatio;
    }

    int shotGlueDotTime() const
    {
        return m_shotGlueDotTime;
    }

    double shotGlueZOffset() const
    {
        return m_shotGlueZOffset;
    }

    QString measureHeightFre() const
    {
        return m_measureHeightFre;
    }

    QString dispensePathFileName() const
    {
        return m_dispensePathFileName;
    }

    bool disableLeftDispHead() const
    {
        return m_disableLeftDispHead;
    }

    double rightDH2LeftDHSafetyRange() const
    {
        return m_rightDH2LeftDHSafetyRange;
    }

    double initAngle() const
    {
        return m_initAngle;
    }

    double readyForDispenseZOffset() const
    {
        return m_readyForDispenseZOffset;
    }

    LaserToCameraOffsetCaliParam *laserToCameraOffsetCaliParam() const
    {
        return m_laserToCameraOffsetCaliParam;
    }

    double measureHeightXShift() const
    {
        return m_measureHeightXShift;
    }

    double measureHeightPosYShift() const
    {
        return m_measureHeightPosYShift;
    }

    bool executeGlueCheck() const
    {
        return m_executeGlueCheck;
    }

    GlueCheckParam *glueCheckParam() const
    {
        return m_glueCheckParam;
    }

    bool disableRightDispHead() const
    {
        return m_disableRightDispHead;
    }

    DispenserConfig *dispenserConfig() const
    {
        return m_dispenserConfig;
    }

    XtFlyDispensingConfig *xtFlyDispensingConfig() const
    {
        return m_xtFlyDispensingConfig;
    }

public slots:
    void setMeasureHeightVelocityRatio(double measureHeightVelocityRatio)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_measureHeightVelocityRatio, measureHeightVelocityRatio))
            return;

        if (measureHeightVelocityRatio > 0.2)
        {
            qCritical("measureHeightVelocityRatio must less than 0.2!");
            emit measureHeightVelocityRatioChanged(m_measureHeightVelocityRatio);
            return;
        }
        m_measureHeightVelocityRatio = measureHeightVelocityRatio;
        emit measureHeightVelocityRatioChanged(m_measureHeightVelocityRatio);
    }

    void setShotGlueDotTime(int shotGlueDotTime)
    {
        if (m_shotGlueDotTime == shotGlueDotTime)
            return;

        m_shotGlueDotTime = shotGlueDotTime;
        emit shotGlueDotTimeChanged(m_shotGlueDotTime);
    }

    void setShotGlueZOffset(double shotGlueOffset)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_shotGlueZOffset, shotGlueOffset))
            return;

        m_shotGlueZOffset = shotGlueOffset;
        emit shotGlueZOffsetChanged(m_shotGlueZOffset);
    }

    void setMeasureHeightFre(QString measureHeightFre)
    {
        if (m_measureHeightFre == measureHeightFre)
            return;

        m_measureHeightFre = measureHeightFre;
        emit measureHeightFreChanged(m_measureHeightFre);
    }

    void setDispensePathFileName(QString dispensePathFileName)
    {
        if (m_dispensePathFileName == dispensePathFileName)
            return;

        m_dispensePathFileName = dispensePathFileName;
        emit dispensePathFileNameChanged(m_dispensePathFileName);
    }

    void setDisableLeftDispHead(bool disableLeftDispHead)
    {
        if (m_disableLeftDispHead == disableLeftDispHead)
            return;

        if (disableLeftDispHead && m_disableRightDispHead)
        {
            qWarning() << tr("Can not disable left and right dispense head at the same time!");
            emit disableLeftDispHeadChanged(m_disableLeftDispHead);
            return;
        }

        m_disableLeftDispHead = disableLeftDispHead;
        emit disableLeftDispHeadChanged(m_disableLeftDispHead);
    }

    void setRightDH2LeftDHSafetyRange(double rightDH2LeftDHSafetyRange)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_rightDH2LeftDHSafetyRange, rightDH2LeftDHSafetyRange))
            return;

        m_rightDH2LeftDHSafetyRange = rightDH2LeftDHSafetyRange;
        emit rightDH2LeftDHSafetyRangeChanged(m_rightDH2LeftDHSafetyRange);
    }

    void setInitAngle(double initAngle)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_initAngle, initAngle))
            return;

        m_initAngle = initAngle;
        emit initAngleChanged(m_initAngle);
    }

    void setReadyForDispenseZOffset(double readyForDispenseZOffset)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_readyForDispenseZOffset, readyForDispenseZOffset))
            return;

        m_readyForDispenseZOffset = readyForDispenseZOffset;
        emit readyForDispenseZOffsetChanged(m_readyForDispenseZOffset);
    }

    void setMeasureHeightXShift(double measureHeightXShift)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_measureHeightXShift, measureHeightXShift))
            return;

        m_measureHeightXShift = measureHeightXShift;
        emit measureHeightXShiftChanged(m_measureHeightXShift);
    }

    void setMeasureHeightPosYShift(double measureHeightPosYShift)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_measureHeightPosYShift, measureHeightPosYShift))
            return;

        m_measureHeightPosYShift = measureHeightPosYShift;
        emit measureHeightPosYShiftChanged(m_measureHeightPosYShift);
    }

    void setExecuteGlueCheck(bool executeGlueCheck)
    {
        if (m_executeGlueCheck == executeGlueCheck)
            return;

        m_executeGlueCheck = executeGlueCheck;
        emit executeGlueCheckChanged(m_executeGlueCheck);
    }

    void setDisableRightDispHead(bool disableRightDispHead)
    {
        if (m_disableRightDispHead == disableRightDispHead)
            return;

        if (disableRightDispHead && m_disableLeftDispHead)
        {
            qWarning() << tr("Can not disable left and right dispense head at the same time!");
            emit disableRightDispHeadChanged(m_disableRightDispHead);
            return;
        }

        m_disableRightDispHead = disableRightDispHead;
        emit disableRightDispHeadChanged(m_disableRightDispHead);
    }

signals:
    void measureHeightVelocityRatioChanged(double measureHeightVelocityRatio);

    void shotGlueDotTimeChanged(int shotGlueDotTime);

    void shotGlueZOffsetChanged(double shotGlueZOffset);

    void measureHeightFreChanged(QString measureHeightFre);

    void dispensePathFileNameChanged(QString dispensePathFileName);

    void disableLeftDispHeadChanged(bool disableLeftDispHead);

    void rightDH2LeftDHSafetyRangeChanged(double rightDH2LeftDHSafetyRange);

    void initAngleChanged(double initAngle);

    void readyForDispenseZOffsetChanged(double readyForDispenseZOffset);

    void measureHeightXShiftChanged(double measureHeightXShift);

    void measureHeightPosYShiftChanged(double measureHeightPosYShift);

    void executeGlueCheckChanged(bool executeGlueCheck);

    void disableRightDispHeadChanged(bool disableRightDispHead);

private:
    double m_measureHeightVelocityRatio = 0.05;
    int m_shotGlueDotTime = 500;
    double m_shotGlueZOffset = 0.1;
    QString m_measureHeightFre;
    QString m_dispensePathFileName = "resultPath.avdata";
    bool m_disableLeftDispHead = false;
    bool m_disableRightDispHead = false;
    double m_rightDH2LeftDHSafetyRange = 0;
    double m_initAngle = 0;
    double m_readyForDispenseZOffset = 2;
    LaserToCameraOffsetCaliParam *m_laserToCameraOffsetCaliParam;
    double m_measureHeightXShift = 0;
    double m_measureHeightPosYShift = 0;
    bool m_executeGlueCheck = false;
    GlueCheckParam *m_glueCheckParam;
    DispenserConfig *m_dispenserConfig;
    XtFlyDispensingConfig *m_xtFlyDispensingConfig;
};

class DispenseHeadConfig : public ConfigObject
{
    Q_OBJECT

    Q_PROPERTY(double measureHeightLimitPos READ measureHeightLimitPos WRITE setMeasureHeightLimitPos NOTIFY
                   measureHeightLimitPosChanged)
    Q_PROPERTY(double laserHeightWhileNozeelTouchedTable READ laserHeightWhileNozeelTouchedTable WRITE
                   setLaserHeightWhileNozeelTouchedTable NOTIFY laserHeightWhileNozeelTouchedTableChanged)

    Q_PROPERTY(double laserToCameraOffsetX READ laserToCameraOffsetX WRITE setLaserToCameraOffsetX NOTIFY
                   laserToCameraOffsetXChanged)
    Q_PROPERTY(double laserToCameraOffsetY READ laserToCameraOffsetY WRITE setLaserToCameraOffsetY NOTIFY
                   laserToCameraOffsetYChanged)

    Q_PROPERTY(double nozeelToCameraOffsetX READ nozeelToCameraOffsetX WRITE setNozeelToCameraOffsetX NOTIFY
                   nozeelToCameraOffsetXChanged)
    Q_PROPERTY(double nozeelToCameraOffsetY READ nozeelToCameraOffsetY WRITE setNozeelToCameraOffsetY NOTIFY
                   nozeelToCameraOffsetYChanged)

    Q_PROPERTY(double shotGlueZHeight READ shotGlueZHeight WRITE setShotGlueZHeight NOTIFY shotGlueZHeightChanged)

    Q_PROPERTY(int shotGlueTimes READ shotGlueTimes WRITE setShotGlueTimes NOTIFY shotGlueTimesChanged)
    Q_PROPERTY(
        QString glueLastSetupTime READ glueLastSetupTime WRITE setGlueLastSetupTime NOTIFY glueLastSetupTimeChanged)

public:
    DispenseHeadConfig(QObject *parent = nullptr) : ConfigObject(parent)
    {
        setReadOnlyProperty("shotGlueTimes");
        init();
    }

    double nozeelToCameraOffsetX() const
    {
        return m_nozeelToCameraOffsetX;
    }

    double nozeelToCameraOffsetY() const
    {
        return m_nozeelToCameraOffsetY;
    }

    double measureHeightLimitPos() const
    {
        return m_measureHeightLimitPos;
    }

    double laserToCameraOffsetX() const
    {
        return m_laserToCameraOffsetX;
    }

    double laserToCameraOffsetY() const
    {
        return m_laserToCameraOffsetY;
    }

    double shotGlueZHeight() const
    {
        return m_shotGlueZHeight;
    }

    double laserHeightWhileNozeelTouchedTable() const
    {
        return m_laserHeightWhileNozeelTouchedTable;
    }

    int shotGlueTimes() const
    {
        return m_shotGlueTimes;
    }

    QString glueLastSetupTime() const
    {
        return m_glueLastSetupTime;
    }

public slots:

    void setNozeelToCameraOffsetX(double nozeelToCameraOffsetX)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_nozeelToCameraOffsetX, nozeelToCameraOffsetX))
            return;

        m_nozeelToCameraOffsetX = nozeelToCameraOffsetX;
        emit nozeelToCameraOffsetXChanged(m_nozeelToCameraOffsetX);
    }

    void setNozeelToCameraOffsetY(double nozeelToCameraOffsetY)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_nozeelToCameraOffsetY, nozeelToCameraOffsetY))
            return;

        m_nozeelToCameraOffsetY = nozeelToCameraOffsetY;
        emit nozeelToCameraOffsetYChanged(m_nozeelToCameraOffsetY);
    }

    void setMeasureHeightLimitPos(double measureHeightLimitPos)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_measureHeightLimitPos, measureHeightLimitPos))
            return;

        m_measureHeightLimitPos = measureHeightLimitPos;
        emit measureHeightLimitPosChanged(m_measureHeightLimitPos);
    }

    void setLaserToCameraOffsetX(double laserToCameraOffsetX)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_laserToCameraOffsetX, laserToCameraOffsetX))
            return;

        m_laserToCameraOffsetX = laserToCameraOffsetX;
        emit laserToCameraOffsetXChanged(m_laserToCameraOffsetX);
    }

    void setLaserToCameraOffsetY(double laserToCameraOffsetY)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_laserToCameraOffsetY, laserToCameraOffsetY))
            return;

        m_laserToCameraOffsetY = laserToCameraOffsetY;
        emit laserToCameraOffsetYChanged(m_laserToCameraOffsetY);
    }

    void setShotGlueZHeight(double shotGlueZHeight)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_shotGlueZHeight, shotGlueZHeight))
            return;

        m_shotGlueZHeight = shotGlueZHeight;
        emit shotGlueZHeightChanged(m_shotGlueZHeight);
    }

    void setLaserHeightWhileNozeelTouchedTable(double laserHeightWhileNozeelTouchedTable)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_laserHeightWhileNozeelTouchedTable, laserHeightWhileNozeelTouchedTable))
            return;

        m_laserHeightWhileNozeelTouchedTable = laserHeightWhileNozeelTouchedTable;
        emit laserHeightWhileNozeelTouchedTableChanged(m_laserHeightWhileNozeelTouchedTable);
    }

    void setShotGlueTimes(int shotGlueTimes)
    {
        if (m_shotGlueTimes == shotGlueTimes)
            return;

        m_shotGlueTimes = shotGlueTimes;
        emit shotGlueTimesChanged(m_shotGlueTimes);
    }

    void setGlueLastSetupTime(QString glueLastSetupTime)
    {
        if (m_glueLastSetupTime == glueLastSetupTime)
            return;

        m_glueLastSetupTime = glueLastSetupTime;
        emit glueLastSetupTimeChanged(m_glueLastSetupTime);
    }

signals:

    void nozeelToCameraOffsetXChanged(double nozeelToCameraOffsetX);

    void nozeelToCameraOffsetYChanged(double nozeelToCameraOffsetY);

    void measureHeightLimitPosChanged(double measureHeightLimitPos);

    void laserToCameraOffsetXChanged(double laserToCameraOffsetX);

    void laserToCameraOffsetYChanged(double laserToCameraOffsetY);

    void shotGlueZHeightChanged(double shotGlueZHeight);

    void laserHeightWhileNozeelTouchedTableChanged(double laserHeightWhileNozeelTouchedTable);

    void shotGlueTimesChanged(int shotGlueTimes);

    void glueLastSetupTimeChanged(QString glueLastSetupTime);

private:
    double m_nozeelToCameraOffsetX = 0;
    double m_nozeelToCameraOffsetY = 0;
    double m_measureHeightLimitPos = 0;
    double m_laserToCameraOffsetX = 0;
    double m_laserToCameraOffsetY = 0;
    double m_shotGlueZHeight = 0;
    double m_laserHeightWhileNozeelTouchedTable = 0;
    int m_shotGlueTimes = 0;
    QString m_glueLastSetupTime;
};

#endif    // DISPENSEHEADCONFIG_H
